package JDBCLEARN;

import org.apache.commons.beanutils.BeanUtils;

import javax.swing.*;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class JdbcReflectToolsTest {
private static String url;
private static String user;
private static String password;
    private static  String driver;
    static {//静态代码块-优先执行
        //I/O使用反射获取i/o流
        InputStream resourceAsStream = JdbcReflectToolsTest.class.getResourceAsStream("jdbcReflect.properties");
        Properties properties = new Properties();//实例化资源包对象
        try {
            properties.load(resourceAsStream);//将资源包内容加载到资源包对象
        } catch (IOException e) {
            e.printStackTrace();
        }
         url = properties.getProperty("url");
        user = properties.getProperty("user");
        password = properties.getProperty("password");
        driver = properties.getProperty("driver");
        //加载驱动
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //释放资源
        if (resourceAsStream!=null){
            try {
                resourceAsStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }


        }



    }

    /**
     *
     * @return
     * @throws SQLException
     */
    //封装数据库链接
    public  static Connection getConnection() throws SQLException {

        Connection connection = DriverManager.getConnection(url, user, password);//获取链接
        System.out.println("11 = " + 11);
        return connection;
    }

    /**
     *
     * @param sql
     * @param connection
     * @param parameters
     * @return
     * @throws SQLException
     */
    //封装预处理
    public static PreparedStatement getPreparedStatement(String sql,Connection connection,Object...parameters) throws SQLException {
        PreparedStatement statement = getConnection().prepareStatement(sql);
        //1.获取元数据
        ParameterMetaData parameterMetaData = statement.getParameterMetaData();
        //2/获取字符串需要的参数个数
        int count = parameterMetaData.getParameterCount();
        //3,判断是否传参，并设置参数
        if (count!=0 && parameters!=null && parameters.length==count){
            for (int i = 0; i < count; i++) {
                statement.setObject(i+1,parameters[i]);

            }

        }




        return statement;
    }


    //封装更新
    public static void updateReflect(String sql,Object...parameters) throws SQLException {
        Connection connection = JdbcReflectToolsTest.getConnection();
        PreparedStatement preparedStatement = JdbcReflectToolsTest.getPreparedStatement(sql,connection,parameters);
        int i = preparedStatement.executeUpdate();
        System.out.println("成功更新 " + i+"条数据");
    }

    /**
     *
     * @param sql
     * @param cls
     * @param parameters
     * @param <T>
     * @return
     * @throws SQLException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    //封装查询（单表单条查询）
    public static <T> T selectReflect(String sql,Class<T> cls,Object...parameters) throws SQLException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //定义需要的变量
        Connection connection;
        PreparedStatement preparedStatement;
        ResultSet resultSet;
        T t=null;
        //获取链接
         connection = JdbcReflectToolsTest.getConnection();
         //获取sql的预处理对象
         preparedStatement = JdbcReflectToolsTest.getPreparedStatement(sql,connection,parameters);//获取预处理对象
        //执行查询获得结果集；
         resultSet = preparedStatement.executeQuery();
         //通过反射获得元数据
        ResultSetMetaData metaData = resultSet.getMetaData();
        //将结果集的元数据整理
        while (resultSet.next()){
             t = cls.newInstance();//实例化一个bean对象，用来封装数据
            int count = metaData.getColumnCount();//获得字段/列数
            for (int i = 1; i < count; i++) {//字段数是从1开始，所以i一定要定义为1
                BeanUtils.setProperty(t,metaData.getColumnName(i),resultSet.getObject(i));//jar包封装好的方法
                /**
                 * BeanUtils.setProperty(t【A】,metaData.getColumnName(i)【B】,resultSet.getObject(i)【C】)
                 *将【B】【C】添加到【A】
                 */
            }

        }


    return t;
    }

    /**
     *
     * @param sql
     * @param cls
     * @param parameters
     * @param <T>
     * @return
     * @throws SQLException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    //封装查询（单表多条查询）
    public static <T> List<T> selectlistReflect(String sql,Class<T> cls,Object...parameters) throws SQLException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //定义需要的变量
        Connection connection;
        PreparedStatement preparedStatement;
        ResultSet resultSet;
        T t=null;
        ArrayList<T> arrayList = new ArrayList<>();//多条查询需要定义集合
        //获取链接
        connection = JdbcReflectToolsTest.getConnection();
        //获取sql的预处理对象
        preparedStatement = JdbcReflectToolsTest.getPreparedStatement(sql,connection,parameters);//获取预处理对象
        //执行查询获得结果集；
        resultSet = preparedStatement.executeQuery();
        //通过反射获得元数据
        ResultSetMetaData metaData = resultSet.getMetaData();
        while (resultSet.next()){
            t = cls.newInstance();//实例化一个bean对象，用来封装数据
            int count = metaData.getColumnCount();//获得字段/列数
            for (int i = 1; i < count; i++) {//字段数是从1开始，所以i一定要定义为1
                BeanUtils.setProperty(t,metaData.getColumnName(i),resultSet.getObject(i));//jar包封装好的方法
                /**
                 * BeanUtils.setProperty(t【A】,metaData.getColumnName(i)【B】,resultSet.getObject(i)【C】)
                 *将【B】【C】添加到【A】
                 */
            }
            arrayList.add(t);//将单条对象添加到集合里

        }

        return arrayList;
    }
    public static void main(String[] args) throws SQLException, InvocationTargetException, InstantiationException, IllegalAccessException {
//        JdbcReflectToolsTest.getConnection();
//        updateReflect("update student set sage=? where sname=? ", 93,"博人");
        Student student = selectReflect("select * from student where sname=?", Student.class, "李同学999");
        System.out.println("student = " + student);
        List<Student> studentList = selectlistReflect("select * from student where sname=?", Student.class, "博人");
        System.out.println("studentList = " + studentList);


    }


}
